package com.ray.ba.starter.code.generator;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import com.ray.ba.starter.code.generator.entity.GenConfig;
import com.ray.ba.starter.code.generator.entity.TableEntity;
import lombok.Data;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * CodeGenerator
 *
 * @author ray
 * @date 2020/5/2
 */
@Data
public class CodeGenerator {

    private static final String TEMPLATE_BASE_DIR = "templates";
    private static final String TEMPLATE_SUFFIX_FTL = ".ftl";

    private GenConfig genConfig;

    private TableEntity tableEntity;

    private List<TemplateResourceEnum> templateResourceList;

    Map<String, String> codeContentMap;

    public static CodeGeneratorBuilder builder() {
        return new CodeGeneratorBuilder();
    }

    public CodeGenerator generate() {
        Dict modelMap = Dict.create().set("genConfig", genConfig).set("tableEntity", tableEntity).set("datetime", LocalDateTime.now()).set("year", LocalDateTime.now().getYear());

        TemplateEngine templateEngine = TemplateUtil.createEngine(new TemplateConfig(TEMPLATE_BASE_DIR, TemplateConfig.ResourceMode.CLASSPATH));
        codeContentMap = templateResourceList.stream().collect(Collectors.toMap(TemplateResourceEnum::name, templateResourceEnum -> {
            Template template = templateEngine.getTemplate(templateResourceEnum.getResourcePath());
            return template.render(modelMap);
        }));
        return this;
    }

    public byte[] getZipContent() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);

        codeContentMap.forEach((templateResourceName, codeContent) -> {
            try {
                zip.putNextEntry(new ZipEntry(getFileName(templateResourceName)));
                IoUtil.write(zip, StandardCharsets.UTF_8, false, codeContent);
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        IoUtil.close(zip);
        return outputStream.toByteArray();
    }


    private String getFileName(String templateResourceName) {
        TemplateResourceEnum templateResourceEnum = TemplateResourceEnum.valueOf(templateResourceName);
        String fileSuffix = "";
        if (!templateResourceEnum.equals(TemplateResourceEnum.ENTITY)) {
            fileSuffix = templateResourceEnum.getResourcePath().substring(0, templateResourceEnum.getResourcePath().indexOf(TEMPLATE_SUFFIX_FTL));
        }

        // 包路径
        StringBuilder sb = new StringBuilder();
        sb.append("ba-gen-code").append(File.separator)
                .append("src").append(File.separator)
                .append("main").append(File.separator)
                .append("java").append(File.separator)
                .append(genConfig.getPackageName().replace(".", File.separator)).append(File.separator)
                .append(genConfig.getModuleName()).append(File.separator)
                .append(templateResourceEnum.getPackagePath().replace(".", File.separator)).append(File.separator)
                .append(tableEntity.getClassName()).append(fileSuffix);
        return sb.toString();
    }


}
